package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.security.SecurityUtils;
import com.zenithmind.note.mapper.NoteCategoryMapper;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.pojo.dto.NoteCategoryDTO;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.entity.NoteCategory;
import com.zenithmind.note.pojo.query.NoteCategoryQuery;
import com.zenithmind.note.pojo.vo.NoteCategoryVO;
import com.zenithmind.note.service.NoteCategoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 笔记分类服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteCategoryServiceImpl extends ServiceImpl<NoteCategoryMapper, NoteCategory> implements NoteCategoryService {

    private final NoteMapper noteMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createCategory(NoteCategoryDTO categoryDTO) {
        // 检查分类名称是否已存在
        String userId = SecurityUtils.getCurrentUserId();
        LambdaQueryWrapper<NoteCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteCategory::getName, categoryDTO.getName())
                .eq(NoteCategory::getUserId, userId);
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException("分类名称已存在");
        }

        // 创建分类
        NoteCategory category = new NoteCategory();
        BeanUtils.copyProperties(categoryDTO, category);
        category.setUserId(userId);
        category.setIsSystem(false);
        if (category.getSort() == null) {
            category.setSort(0);
        }
        this.save(category);
        return category.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCategory(NoteCategoryDTO categoryDTO) {
        // 检查分类是否存在
        NoteCategory category = this.getById(categoryDTO.getId());
        if (category == null) {
            throw new BusinessException("分类不存在");
        }

        // 检查是否有权限修改
        String userId = SecurityUtils.getCurrentUserId();
        if (!userId.equals(category.getUserId())) {
            throw new BusinessException("无权修改此分类");
        }

        // 检查系统预设分类
        if (Boolean.TRUE.equals(category.getIsSystem())) {
            throw new BusinessException("系统预设分类不可修改");
        }

        // 检查分类名称是否已存在
        LambdaQueryWrapper<NoteCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteCategory::getName, categoryDTO.getName())
                .eq(NoteCategory::getUserId, userId)
                .ne(NoteCategory::getId, categoryDTO.getId());
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException("分类名称已存在");
        }

        // 更新分类
        BeanUtils.copyProperties(categoryDTO, category);
        this.updateById(category);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCategory(String id) {
        // 检查分类是否存在
        NoteCategory category = this.getById(id);
        if (category == null) {
            throw new BusinessException("分类不存在");
        }

        // 检查是否有权限删除
        String userId = SecurityUtils.getCurrentUserId();
        if (!userId.equals(category.getUserId())) {
            throw new BusinessException("无权删除此分类");
        }

        // 检查系统预设分类
        if (Boolean.TRUE.equals(category.getIsSystem())) {
            throw new BusinessException("系统预设分类不可删除");
        }

        // 检查是否有笔记使用此分类
        LambdaQueryWrapper<Note> noteQueryWrapper = new LambdaQueryWrapper<>();
        noteQueryWrapper.eq(Note::getCategoryId, id);
        long count = noteMapper.selectCount(noteQueryWrapper);
        if (count > 0) {
            throw new BusinessException("该分类下有笔记，不可删除");
        }

        // 删除分类
        this.removeById(id);
    }

    @Override
    public NoteCategoryVO getCategoryDetail(String id) {
        NoteCategory category = this.getById(id);
        if (category == null) {
            throw new BusinessException("分类不存在");
        }

        // 如果不是系统预设分类，检查是否有权限查看
        if (Boolean.FALSE.equals(category.getIsSystem())) {
            String userId = SecurityUtils.getCurrentUserId();
            if (!userId.equals(category.getUserId())) {
                throw new BusinessException("无权查看此分类");
            }
        }

        // 查询笔记数量
        LambdaQueryWrapper<Note> noteQueryWrapper = new LambdaQueryWrapper<>();
        noteQueryWrapper.eq(Note::getCategoryId, id);
        long noteCount = noteMapper.selectCount(noteQueryWrapper);
        
        // 转换为VO
        NoteCategoryVO vo = new NoteCategoryVO();
        BeanUtils.copyProperties(category, vo);
        vo.setNoteCount((int) noteCount);
        return vo;
    }

    @Override
    public PageResult<NoteCategoryVO> categoryPage(NoteCategoryQuery query) {
        // 构建查询条件
        LambdaQueryWrapper<NoteCategory> queryWrapper = new LambdaQueryWrapper<>();
        
        // 如果没有指定用户ID，使用当前登录用户
        String userId = query.getUserId();
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
            query.setUserId(userId);
        }
        
        // 添加查询条件
        queryWrapper.eq(StringUtils.isNotBlank(query.getUserId()), NoteCategory::getUserId, query.getUserId())
                .eq(query.getIsSystem() != null, NoteCategory::getIsSystem, query.getIsSystem())
                .eq(StringUtils.isNotBlank(query.getParentId()), NoteCategory::getParentId, query.getParentId())
                .like(StringUtils.isNotBlank(query.getName()), NoteCategory::getName, query.getName())
                .orderByAsc(NoteCategory::getSort)
                .orderByDesc(NoteCategory::getCreateTime);

        // 分页查询
        Page<NoteCategory> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<NoteCategory> categoryPage = this.page(page, queryWrapper);
        
        // 查询笔记数量
        List<NoteCategoryVO> voList = new ArrayList<>();
        if (categoryPage.getRecords().isEmpty()) {
            return PageResult.of(voList, categoryPage.getTotal(), query.getCurrent().longValue(), query.getSize().longValue());
        }
        
        // 批量查询笔记数量
        List<String> categoryIds = categoryPage.getRecords().stream()
                .map(NoteCategory::getId)
                .collect(Collectors.toList());
        
        // 使用Map存储分类ID和笔记数量的映射
        Map<String, Long> categoryNoteCountMap = getCategoryNoteCountMap(categoryIds);
        
        // 转换为VO
        for (NoteCategory category : categoryPage.getRecords()) {
            NoteCategoryVO vo = new NoteCategoryVO();
            BeanUtils.copyProperties(category, vo);
            Long noteCount = categoryNoteCountMap.getOrDefault(category.getId(), 0L);
            vo.setNoteCount(noteCount.intValue());
            voList.add(vo);
        }
        
        return PageResult.of(voList, categoryPage.getTotal(), query.getCurrent().longValue(), query.getSize().longValue());
    }

    @Override
    public List<NoteCategoryVO> getUserCategories(String userId) {
        try {
            // 如果没有指定用户ID，使用当前登录用户
            if (StringUtils.isBlank(userId)) {
                userId = SecurityUtils.getCurrentUserId();
                // 如果用户未登录，则只返回系统分类
                if (StringUtils.isBlank(userId)) {
                    log.info("用户未登录，只返回系统分类");
                    return getSystemCategories();
                }
            }
            
            // 查询用户的分类列表
            LambdaQueryWrapper<NoteCategory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NoteCategory::getUserId, userId)
                    .or()
                    .eq(NoteCategory::getIsSystem, true)
                    .orderByAsc(NoteCategory::getSort)
                    .orderByDesc(NoteCategory::getCreateTime);
            List<NoteCategory> categoryList = this.list(queryWrapper);
            
            if (categoryList.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 批量查询笔记数量
            List<String> categoryIds = categoryList.stream()
                    .map(NoteCategory::getId)
                    .collect(Collectors.toList());
            
            // 使用Map存储分类ID和笔记数量的映射
            Map<String, Long> categoryNoteCountMap = getCategoryNoteCountMap(categoryIds);
            
            // 转换为VO
            List<NoteCategoryVO> voList = new ArrayList<>();
            for (NoteCategory category : categoryList) {
                NoteCategoryVO vo = new NoteCategoryVO();
                BeanUtils.copyProperties(category, vo);
                Long noteCount = categoryNoteCountMap.getOrDefault(category.getId(), 0L);
                vo.setNoteCount(noteCount.intValue());
                voList.add(vo);
            }
            
            return voList;
        } catch (Exception e) {
            log.error("获取用户分类列表异常", e);
            // 发生异常时返回空列表而不是抛出异常
            return new ArrayList<>();
        }
    }

    @Override
    public List<NoteCategoryVO> getSystemCategories() {
        // 查询系统预设分类
        LambdaQueryWrapper<NoteCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteCategory::getIsSystem, true)
                .orderByAsc(NoteCategory::getSort)
                .orderByDesc(NoteCategory::getCreateTime);
        List<NoteCategory> categoryList = this.list(queryWrapper);
        
        if (categoryList.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 批量查询笔记数量
        List<String> categoryIds = categoryList.stream()
                .map(NoteCategory::getId)
                .collect(Collectors.toList());
        
        // 使用Map存储分类ID和笔记数量的映射
        Map<String, Long> categoryNoteCountMap = getCategoryNoteCountMap(categoryIds);
        
        // 转换为VO
        List<NoteCategoryVO> voList = new ArrayList<>();
        for (NoteCategory category : categoryList) {
            NoteCategoryVO vo = new NoteCategoryVO();
            BeanUtils.copyProperties(category, vo);
            Long noteCount = categoryNoteCountMap.getOrDefault(category.getId(), 0L);
            vo.setNoteCount(noteCount.intValue());
            voList.add(vo);
        }
        
        return voList;
    }

    @Override
    public List<NoteCategoryVO> getCategoryStats(String userId) {
        // 如果没有指定用户ID，使用当前登录用户
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
        }
        
        // 获取用户的分类列表
        return getUserCategories(userId);
    }
    
    /**
     * 获取分类ID和笔记数量的映射
     * 
     * @param categoryIds 分类ID列表
     * @return 分类ID和笔记数量的映射
     */
    private Map<String, Long> getCategoryNoteCountMap(List<String> categoryIds) {
        LambdaQueryWrapper<Note> noteQueryWrapper = new LambdaQueryWrapper<>();
        noteQueryWrapper.in(Note::getCategoryId, categoryIds);
        List<Note> noteList = noteMapper.selectList(noteQueryWrapper);
        
        // 统计每个分类下的笔记数量
        return noteList.stream()
                .collect(Collectors.groupingBy(Note::getCategoryId, Collectors.counting()));
    }
} 